/*
 * DynamicStreetLightTests.java
 * 
 * Created on Jun 5, 2007, 12:17:30 AM
 * 
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.infomancers.workflow;

import com.infomancers.collections.actions.ValueSetterAction;
import com.infomancers.workflow.*;
import com.infomancers.workflow.tests.Light;
import com.infomancers.workflow.tests.PredicatedLight;
import com.infomancers.workflow.concrete.ConcretePlace;
import com.infomancers.workflow.dynamic.*;
import com.infomancers.workflow.managers.ConcurrentFlowManager;
import com.infomancers.workflow.managers.SynchroniousFlowManager;
import com.infomancers.workflow.tests.DebuggingFlowManager;
import junit.framework.JUnit4TestAdapter;
import org.junit.Test;
import static org.junit.Assert.*;


/**
 *
 * @author aviadbd
 */
public class DynamicStreetLightTests {
    private WorkflowBuilder getStreetLightWorkflowBuilder(int id) {
        WorkflowBuilder builder = new WorkflowBuilder();
        
        Place red = new ConcretePlace("red" + id);
        Place green = new ConcretePlace("green" + id);
        
        DynamicPlace control = new DynamicPlace();
        DynamicPlace input = new DynamicPlace();
        DynamicPlace output = new DynamicPlace();

        control.setPredicate(new PlacePropertyPredicate("isControl", "true"));
        input.setPredicate(new PlacePropertyPredicate("isInput", "true"));
        output.setPredicate(new PlacePropertyPredicate("isOutput", "true"));
        
        Transition rg = new Transition();
        Transition gr = new Transition();
        Transition sw = new Transition();
        
        sw.setPredicate(new PredicatedLight(id));
        rg.setAction(new ValueSetterAction<Object>("light", id));
        
        builder.addConnection(input, sw);
        builder.addConnection(sw, red);
        builder.addConnection(sw, control);
        builder.addConnection(control, rg);
        builder.addConnection(red, rg);
        builder.addConnection(rg, green);
        builder.addConnection(green, gr);
        builder.addConnection(gr, output);
        
        return builder;
    }
    
    private Workflow createMainFlow(FlowManager manager, int... ids) {
        WorkflowBuilder builder = new WorkflowBuilder();
        
        ConcretePlace input = new ConcretePlace("input");
        ConcretePlace output = new ConcretePlace("output");
        ConcretePlace control = new ConcretePlace("control");
        
        input.getProperties().put("isInput", "true");
        output.getProperties().put("isOutput", "true");
        control.getProperties().put("isControl", "true");
        
        builder.addDisconnectedPlace(input);
        builder.addDisconnectedPlace(control);
        builder.addDisconnectedPlace(output);
        
        for (int id : ids) {
            builder.addWorkflowBuilder(getStreetLightWorkflowBuilder(id));
        }
        
        return builder.createWorkflow(input, output, manager);
    }
    
    public static junit.framework.Test suite() {
        return new JUnit4TestAdapter(DynamicStreetLightTests.class);
    }
    
    @Test
    public void creation() {
        FlowManager manager = new ConcurrentFlowManager();
        Workflow flow = createMainFlow(manager, 1, 2);
        
        assertNotNull(flow);
    }
    
    @Test
    public void green1() {
        Workflow flow = createMainFlow(new SynchroniousFlowManager(), 1, 2);
        
        WorkflowQueue queue = new WorkflowQueue(flow);
        queue.pushData(new Light(1));
        assertTrue(queue.hasData());
        Light light = (Light) queue.pullData();
        
        assertEquals(light.getWanted(), 1);
        assertEquals(light.getWanted(), light.getLight());
    }

    @Test
    public void green2() {
        Workflow flow = createMainFlow(new SynchroniousFlowManager(), 1, 2);
        
        WorkflowQueue queue = new WorkflowQueue(flow);
        queue.pushData(new Light(2));
        assertTrue(queue.hasData());
        Light light = (Light) queue.pullData();
        
        assertEquals(light.getWanted(), 2);
        assertEquals(light.getWanted(), light.getLight());
    }
    
    @Test
    public void green3() {
        Workflow flow = createMainFlow(new SynchroniousFlowManager(), 1, 2);
        
        WorkflowQueue queue = new WorkflowQueue(flow);
        queue.pushData(new Light(3));
        
        assertFalse(queue.hasData());
    }
    
    @Test
    public void multipleTries() {
        Workflow flow = createMainFlow(new DebuggingFlowManager(), 1, 2);
        
        WorkflowQueue queue = new WorkflowQueue(flow);
        queue.pushData(new Light(1));
        queue.pushData(new Light(2));
        queue.pushData(new Light(3));
        
        assertTrue(queue.hasData());
        Light light = (Light) queue.pullData();
        assertEquals(light.getLight(), light.getWanted());
        assertEquals(light.getWanted(), 1);

        assertTrue(queue.hasData());
        light = (Light) queue.pullData();
        assertEquals(light.getLight(), light.getWanted());
        assertEquals(light.getWanted(), 2);
        
        assertFalse(queue.hasData());
    }
}
